/*Copyright (C) 2009 - 2011 MASSART GAUTHIER

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "../headers.h"

int tetris_lignes;
int tetris_points;
int tetris_niveau;
int tetris_nombre_lignes_debut;
int tetris_premier_appel;
int tetris_ancien_niveau;
int tetris_meilleur_score;

void tet_jeu(void) {
	int action = 0/*, toucheAppuyee = 0*//* entrees(getch()) */, i, perdu = 0, reserveDispo = 1;
	/* represente le plateau de jeu. contient la couleur du bloc ou 0(TET_VIDE) si la case est vide */
	int matrice[TET_LARGEUR][TET_HAUTEUR] = {{0}};
	/* coordonnees y des lignes a enlever(max : 4) */
	int lignesPleines[4] = {0};
	/* Temps d'attente en ms pour que la piece descende d'un cran */
	short tabtetris_niveaux[20] = {
		1500, 1200, 1000, 800, 650, 450, 300, 200, 150,
		120, 100, 90, 80, 75, 70, 65, 60, 55, 50, 1
	};
	long dernierT = 0; /* temps du dernier get_time_ms() */
	long continuer = 0, fin = 0, choix = 0;
	/* donnees des 7 pieces differentes(initialisation dans init()) */
	forme pieces[7] = {{{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, 0, 0, 0}};
	forme pieceAct; /* donnees de la piece en mouvement */
	forme pieceProch; /* donnees de la piece en attente */
	forme reserve;
	reserve.couleur = 0; /* =0 si la reserve est vide */

	tetris_niveau = 1;
	tetris_lignes = 0;
	tetris_points = 0;
	tetris_nombre_lignes_debut = 8;
	tetris_premier_appel = 0;
	tetris_ancien_niveau = 0;
	clear();

	afficher_titre("TETRIS");
	CSLP_ColorText(CT);
	addstr("\n\nPour augmenter le nombre de lignes de handicap au début, appuyer sur → .\nPour diminuer le nombre de lignes de handicap au début, appuyer sur ← .\n\nLe le nombre de lignes de handicap actuel est :\n");

	tetris_nombre_lignes_debut = afficher_barre_full(0, 15, 1, tetris_nombre_lignes_debut);

	/* Recuperation de l'ancien meilleur score */
	if(lire_suppr_score("Tetris", true) != -1)
		tetris_meilleur_score = lire_suppr_score("Tetris", true);

	/* INIT */

	tet_init(pieces);

	tet_affiche_legende();

	for(i = 0; i < tetris_nombre_lignes_debut; i++)
		rajouter_ligne(matrice);

	nouvelle_piece(matrice, pieces, &pieceAct, &pieceProch, NULL);

	nouvelle_piece(matrice, pieces, &pieceAct, &pieceProch, NULL);

	dernierT = get_time_ms();

	/* Boucle principale */
	while(fin != 1) {
		/* si la piece arrive en bas */
		if(tet_bouger(matrice, action = recup_event()/* entrees ici!!! */, &pieceAct)) {
			verif_ligne_pleine(matrice, lignesPleines);
			tet_animation_enlever_ligne(matrice, lignesPleines);
			perdu = nouvelle_piece(matrice, pieces, &pieceAct, &pieceProch, NULL);
			reserveDispo = 1;
		}

		if(action == BAS || action == HAUT)
			dernierT = get_time_ms();

		/* Si le joueur a appuye sur r et qu'il ne l'a pas fait juste avant*/
		if(action == TET_RESERVE && reserveDispo) {
			jouer_son(TETRISTOURNER);
			/* echange pieceAct <-> reserve */
			perdu = nouvelle_piece(matrice, pieces, &pieceAct, &pieceProch, &reserve);
			/* affichage... */
			s_occuper_reserve(&reserve);
			/* le joueur ne peut plus utiliser la reserve avant d'avoir pose une piece */
			reserveDispo = 0;
			dernierT = get_time_ms();
		}

		if(action == TET_QUITTER) {
			clear();
			nodelay(stdscr, 0);
			choix = afficher_menu("Oui\nNon\n", "Voulez-vous vraiment quitter la partie en cours ?\n", "TETRIS");
			nodelay(stdscr, 1);
			if(choix == 1) {
				fin = 1;
				clear();
			}
			else {
				clear();
				tet_affiche_legende();
				tet_afficher(matrice);
				tetris_ancien_niveau--;
				afficher_cadre_tetris();
			}

			dernierT = get_time_ms();
		}

		/* si l'intervalle de temps > celle du niveau actuel, on descend la piece d'un cran */
		if(get_time_ms() - dernierT > tabtetris_niveaux[tetris_niveau - 1]) {
			if(descendre_piece(matrice, &pieceAct)) {  /* si la piece arrive en bas */
				jouer_son(TETRISENBAS);
				verif_ligne_pleine(matrice, lignesPleines);
				tet_animation_enlever_ligne(matrice, lignesPleines);
				perdu = nouvelle_piece(matrice, pieces, &pieceAct, &pieceProch, NULL);
				reserveDispo = 1;
			}

			dernierT = get_time_ms();
		}

		afficher_fantome(matrice, pieceAct);

		tet_afficher(matrice);
		afficher_cadre_tetris();

		if(perdu) {
			animation_perdu(matrice);

			if(tetris_points > tetris_meilleur_score) {
				char score[10];
				CSLP_Color(CT, COLOR_BLACK);
				move(TET_POS_MAT_Y + 4, 0);
				afficher_centre("FELICITATION !");
				move(TET_POS_MAT_Y + 6, 0);
				afficher_centre("MEILLEUR SCORE");
				move(TET_POS_MAT_Y + 7, 0);
				afficher_centre("BATTU!!!");
				move(TET_POS_MAT_Y + 9, 0);
				afficher_centre("ANCIEN SCORE");
				CSLP_ColorText(COLOR_RED);
				move(TET_POS_MAT_Y + 10, 0);
				sprintf(score, "%d", tetris_meilleur_score);
				afficher_centre(score);
				CSLP_ColorText(CT);
				move(TET_POS_MAT_Y + 12, 0);
				afficher_centre("NOUVEAU SCORE");
				CSLP_ColorText(COLOR_GREEN);
				move(TET_POS_MAT_Y + 13, 0);
				sprintf(score, "%d", tetris_points);
				afficher_centre(score);
				CSLP_Color(COLOR_BLACK, COLOR_BLACK);
				refresh();
				save_score("Tetris", tetris_points, 0, 0);
				afficher_temps(TET_POS_MAT_Y + 15, 'm', 2, 5000);
				tetris_meilleur_score = tetris_points;
			}

			/* Re-inits */

			clear();
			continuer = afficher_menu_recommencer("TETRIS");
			clear();

			if(continuer == 1) {

				tet_affiche_legende();

				for(i = 0; i < tetris_nombre_lignes_debut; i++)
					rajouter_ligne(matrice);

				tetris_niveau = 1;
				tetris_lignes = 0;
				tetris_points = 0;
				tetris_premier_appel = 0;
				tetris_ancien_niveau = 0;
				dernierT = get_time_ms();
				perdu = 0;
				nouvelle_piece(matrice, pieces, &pieceAct, &pieceProch, NULL);
				tet_afficher(matrice);
				reserveDispo = 1;
				reserve.couleur = 0;
				s_occuper_reserve(&reserve);

				while(getch() != ERR);
			}
			else
				fin = 1;

		}

		tetris_niveau = tetris_lignes / 10 + 1;

		CSLP_Sleep(1);
	}/* Fin boucle principale */

	clear();

	nodelay(stdscr, 0);
	music_loop(false);

	if(is_music_stoped() == false) {
		next_music();
	}

	return;
}

/*******************************************/

void tet_init(forme pieces[]) {
	int i;

	clear();
	/*keypad(stdscr, TRUE);*/
	nodelay(stdscr, 1);
	/*  start_CSLP_Color();*/

	play_music(TETRIS);
	music_loop(true);

	for(i = 0; i < 20; i++)
		rand();/* premiers rand() pas vraiment aleatoires */

	/* init pieces */
	pieces[0].posP[1].x = 1;
	pieces[0].posP[2].x = 2;/* HHHH */
	pieces[0].posP[3].x = 3;
	pieces[0].blocTourne = 2;
	pieces[0].type = 0;
	pieces[0].couleur = COLOR_WHITE;

	pieces[1].posP[1].x = 1;
	pieces[1].posP[2].x = 2;/* HHH */
	pieces[1].posP[3].y = 1;/* H   */
	pieces[1].blocTourne = 1;
	pieces[1].type = 1;
	pieces[1].couleur = COLOR_CYAN;


	pieces[2].posP[1].x = 1;
	pieces[2].posP[2].x = 2;/* HHH */
	pieces[2].posP[3].x = 2;/*   H */
	pieces[2].posP[3].y = 1;
	pieces[2].blocTourne = 1;
	pieces[2].type = 2;
#ifdef WIN32
	pieces[2].couleur = 100;
#else
	pieces[2].couleur = COLOR_BLUE;
#endif

	pieces[3].posP[1].x = 1;
	pieces[3].posP[2].x = 2;/* HHH */
	pieces[3].posP[3].x = 1;/*  H  */
	pieces[3].posP[3].y = 1;
	pieces[3].blocTourne = 1;
	pieces[3].type = 3;
	pieces[3].couleur = COLOR_MAGENTA;

	pieces[4].posP[1].x = 1;
	pieces[4].posP[2].x = 1;/* HH */
	pieces[4].posP[2].y = 1;/* HH */
	pieces[4].posP[3].y = 1;
	pieces[4].blocTourne = 1;
	pieces[4].type = 4;
	pieces[4].couleur = COLOR_YELLOW;

	pieces[5].posP[1].x = 1;
	pieces[5].posP[2].x = 1;/* HH  */
	pieces[5].posP[2].y = 1;/*  HH */
	pieces[5].posP[3].x = 2;
	pieces[5].posP[3].y = 1;
	pieces[5].blocTourne = 1;
	pieces[5].type = 5;
#ifdef WIN32
	pieces[5].couleur = COLOR_RED;
#else
	pieces[5].couleur = 100;
#endif

	pieces[6].posP[0].x = 1;
	pieces[6].posP[1].x = 2;/*  HH */
	pieces[6].posP[2].y = 1;/* HH  */
	pieces[6].posP[3].x = 1;
	pieces[6].posP[3].y = 1;
	pieces[6].blocTourne = 3;
	pieces[6].type = 6;
	pieces[6].couleur = COLOR_GREEN;

}

/*******************************************/

void verif_ligne_pleine(int matrice[][TET_HAUTEUR], int lignesPleines[]) {
	int i, j, nbtetris_lignes = 0, lignePleine = 0;

	for(j = 0; j < TET_HAUTEUR; j++) {
		lignePleine = 1;

		for(i = 0; i < TET_LARGEUR; i++) {
			if(matrice[i][j] == TET_VIDE)
				lignePleine = 0;
		}

		if(lignePleine)
			lignesPleines[nbtetris_lignes++] = j;
	}

}

/*******************************************/

void tet_tourner_forme(forme *aTourner) {
	int buff = aTourner->posP[0].x;

	aTourner->posP[0].x = aTourner->posP[aTourner->blocTourne].x + (aTourner->posP[0].y - aTourner->posP[aTourner->blocTourne].y);
	aTourner->posP[0].y = aTourner->posP[aTourner->blocTourne].y - (buff - aTourner->posP[aTourner->blocTourne].x);

	buff = aTourner->posP[1].x;
	aTourner->posP[1].x = aTourner->posP[aTourner->blocTourne].x + (aTourner->posP[1].y - aTourner->posP[aTourner->blocTourne].y);
	aTourner->posP[1].y = aTourner->posP[aTourner->blocTourne].y - (buff - aTourner->posP[aTourner->blocTourne].x);

	buff = aTourner->posP[2].x;
	aTourner->posP[2].x = aTourner->posP[aTourner->blocTourne].x + (aTourner->posP[2].y - aTourner->posP[aTourner->blocTourne].y);
	aTourner->posP[2].y = aTourner->posP[aTourner->blocTourne].y - (buff - aTourner->posP[aTourner->blocTourne].x);

	buff = aTourner->posP[3].x;
	aTourner->posP[3].x = aTourner->posP[aTourner->blocTourne].x + (aTourner->posP[3].y - aTourner->posP[aTourner->blocTourne].y);
	aTourner->posP[3].y = aTourner->posP[aTourner->blocTourne].y - (buff - aTourner->posP[aTourner->blocTourne].x);

	if(aTourner->posP[0].y == -2 || aTourner->posP[1].y == -2 || aTourner->posP[2].y == -2 || aTourner->posP[3].y == -2) {
		aTourner->posP[0].y += 2;
		aTourner->posP[1].y += 2;
		aTourner->posP[2].y += 2;
		aTourner->posP[3].y += 2;
	}
	else if(aTourner->posP[0].y == -1 || aTourner->posP[1].y == -1 || aTourner->posP[2].y == -1 || aTourner->posP[3].y == -1) {
		aTourner->posP[0].y += 1;
		aTourner->posP[1].y += 1;
		aTourner->posP[2].y += 1;
		aTourner->posP[3].y += 1;
	}
	else if(aTourner->posP[0].y == TET_HAUTEUR + 1 || aTourner->posP[1].y == TET_HAUTEUR + 1 || aTourner->posP[2].y == TET_HAUTEUR + 1 || aTourner->posP[3].y == TET_HAUTEUR + 1) {
		aTourner->posP[0].y -= 2;
		aTourner->posP[1].y -= 2;
		aTourner->posP[2].y -= 2;
		aTourner->posP[3].y -= 2;
	}
	else if(aTourner->posP[0].y == TET_HAUTEUR || aTourner->posP[1].y == TET_HAUTEUR || aTourner->posP[2].y == TET_HAUTEUR || aTourner->posP[3].y == TET_HAUTEUR) {
		aTourner->posP[0].y -= 1;
		aTourner->posP[1].y -= 1;
		aTourner->posP[2].y -= 1;
		aTourner->posP[3].y -= 1;
	}

	if(aTourner->posP[0].x == -2 || aTourner->posP[1].x == -2 || aTourner->posP[2].x == -2 || aTourner->posP[3].x == -2) {
		aTourner->posP[0].x += 2;
		aTourner->posP[1].x += 2;
		aTourner->posP[2].x += 2;
		aTourner->posP[3].x += 2;
	}
	else if(aTourner->posP[0].x == -1 || aTourner->posP[1].x == -1 || aTourner->posP[2].x == -1 || aTourner->posP[3].x == -1) {
		aTourner->posP[0].x += 1;
		aTourner->posP[1].x += 1;
		aTourner->posP[2].x += 1;
		aTourner->posP[3].x += 1;
	}
	else if(aTourner->posP[0].x == TET_LARGEUR + 1 || aTourner->posP[1].x == TET_LARGEUR + 1 || aTourner->posP[2].x == TET_LARGEUR + 1 || aTourner->posP[3].x == TET_LARGEUR + 1) {
		aTourner->posP[0].x -= 2;
		aTourner->posP[1].x -= 2;
		aTourner->posP[2].x -= 2;
		aTourner->posP[3].x -= 2;
	}
	else if(aTourner->posP[0].x == TET_LARGEUR || aTourner->posP[1].x == TET_LARGEUR || aTourner->posP[2].x == TET_LARGEUR || aTourner->posP[3].x == TET_LARGEUR) {
		aTourner->posP[0].x -= 1;
		aTourner->posP[1].x -= 1;
		aTourner->posP[2].x -= 1;
		aTourner->posP[3].x -= 1;
	}

}

/*******************************************/

void tet_tourner(int matrice[][TET_HAUTEUR], forme *piece) {
	if(piece->type != 4) {
		forme copieP = *piece;

		tet_tourner_forme(&copieP);

		matrice[piece->posP[0].x][piece->posP[0].y] = TET_VIDE;
		matrice[piece->posP[1].x][piece->posP[1].y] = TET_VIDE;
		matrice[piece->posP[2].x][piece->posP[2].y] = TET_VIDE;
		matrice[piece->posP[3].x][piece->posP[3].y] = TET_VIDE;

		if(matrice[copieP.posP[0].x][copieP.posP[0].y] == TET_VIDE &&
		matrice[copieP.posP[1].x][copieP.posP[1].y] == TET_VIDE &&
		matrice[copieP.posP[2].x][copieP.posP[2].y] == TET_VIDE &&
		matrice[copieP.posP[3].x][copieP.posP[3].y] == TET_VIDE) {

			matrice[copieP.posP[0].x][copieP.posP[0].y] = piece->couleur;
			matrice[copieP.posP[1].x][copieP.posP[1].y] = piece->couleur;
			matrice[copieP.posP[2].x][copieP.posP[2].y] = piece->couleur;
			matrice[copieP.posP[3].x][copieP.posP[3].y] = piece->couleur;
			*piece = copieP;
		}
		else {
			matrice[piece->posP[0].x][piece->posP[0].y] = piece->couleur;
			matrice[piece->posP[1].x][piece->posP[1].y] = piece->couleur;
			matrice[piece->posP[2].x][piece->posP[2].y] = piece->couleur;
			matrice[piece->posP[3].x][piece->posP[3].y] = piece->couleur;

		}
	}
}

/*******************************************/

int tet_bouger(int matrice[][TET_HAUTEUR], int comment, forme *laPiece) {
	int retour = 0;

	switch(comment) {

	case ERR:
		break;
	case BAS:
		if(descendre_piece(matrice, laPiece)) {
			jouer_son(TETRISENBAS);
			retour = 1;
		}
		else
			{}
		break;
	case HAUT:
		while(descendre_piece(matrice, laPiece) == 0);

		retour = 1;

		jouer_son(TETRISENBAS);
		break;
	case TET_TOURNER:
		tet_tourner(matrice, laPiece);

		jouer_son(TETRISTOURNER);
		break;
	case GAUCHE:
		if(laPiece->posP[0].x && laPiece->posP[1].x &&
		laPiece->posP[2].x && laPiece->posP[3].x) {
			if((matrice[laPiece->posP[0].x - 1][laPiece->posP[0].y] == TET_VIDE
			|| (laPiece->posP[0].x - 1 == laPiece->posP[1].x && laPiece->posP[0].y == laPiece->posP[1].y)
			|| (laPiece->posP[0].x - 1 == laPiece->posP[2].x && laPiece->posP[0].y == laPiece->posP[2].y)
			|| (laPiece->posP[0].x - 1 == laPiece->posP[3].x && laPiece->posP[0].y == laPiece->posP[3].y))
			&& (matrice[laPiece->posP[1].x - 1][laPiece->posP[1].y] == TET_VIDE
			|| (laPiece->posP[1].x - 1 == laPiece->posP[0].x && laPiece->posP[1].y == laPiece->posP[0].y)
			|| (laPiece->posP[1].x - 1 == laPiece->posP[2].x && laPiece->posP[1].y == laPiece->posP[2].y)
			|| (laPiece->posP[1].x - 1 == laPiece->posP[3].x && laPiece->posP[1].y == laPiece->posP[3].y))
			&& (matrice[laPiece->posP[2].x - 1][laPiece->posP[2].y] == TET_VIDE
			|| (laPiece->posP[2].x - 1 == laPiece->posP[1].x && laPiece->posP[2].y == laPiece->posP[1].y)
			|| (laPiece->posP[2].x - 1 == laPiece->posP[0].x && laPiece->posP[2].y == laPiece->posP[0].y)
			|| (laPiece->posP[2].x - 1 == laPiece->posP[3].x && laPiece->posP[2].y == laPiece->posP[3].y))
			&& (matrice[laPiece->posP[3].x - 1][laPiece->posP[3].y] == TET_VIDE
			|| (laPiece->posP[3].x - 1 == laPiece->posP[1].x && laPiece->posP[3].y == laPiece->posP[1].y)
			|| (laPiece->posP[3].x - 1 == laPiece->posP[2].x && laPiece->posP[3].y == laPiece->posP[2].y)
			|| (laPiece->posP[3].x - 1 == laPiece->posP[0].x && laPiece->posP[3].y == laPiece->posP[0].y))) {
				matrice[laPiece->posP[0].x][laPiece->posP[0].y] = TET_VIDE;
				matrice[laPiece->posP[1].x][laPiece->posP[1].y] = TET_VIDE;
				matrice[laPiece->posP[2].x][laPiece->posP[2].y] = TET_VIDE;
				matrice[laPiece->posP[3].x][laPiece->posP[3].y] = TET_VIDE;

				matrice[laPiece->posP[0].x -= 1][laPiece->posP[0].y] = laPiece->couleur;
				matrice[laPiece->posP[1].x -= 1][laPiece->posP[1].y] = laPiece->couleur;
				matrice[laPiece->posP[2].x -= 1][laPiece->posP[2].y] = laPiece->couleur;
				matrice[laPiece->posP[3].x -= 1][laPiece->posP[3].y] = laPiece->couleur;
			}
		}
		break;
	case DROITE:

		if(laPiece->posP[0].x < TET_LARGEUR - 1 && laPiece->posP[1].x < TET_LARGEUR - 1 &&
		laPiece->posP[2].x < TET_LARGEUR - 1 && laPiece->posP[3].x < TET_LARGEUR - 1) {
			if((matrice[laPiece->posP[0].x + 1][laPiece->posP[0].y] == TET_VIDE
			|| (laPiece->posP[0].x + 1 == laPiece->posP[1].x && laPiece->posP[0].y == laPiece->posP[1].y)
			|| (laPiece->posP[0].x + 1 == laPiece->posP[2].x && laPiece->posP[0].y == laPiece->posP[2].y)
			|| (laPiece->posP[0].x + 1 == laPiece->posP[3].x && laPiece->posP[0].y == laPiece->posP[3].y))
			&& (matrice[laPiece->posP[1].x + 1][laPiece->posP[1].y] == TET_VIDE
			|| (laPiece->posP[1].x + 1 == laPiece->posP[0].x && laPiece->posP[1].y == laPiece->posP[0].y)
			|| (laPiece->posP[1].x + 1 == laPiece->posP[2].x && laPiece->posP[1].y == laPiece->posP[2].y)
			|| (laPiece->posP[1].x + 1 == laPiece->posP[3].x && laPiece->posP[1].y == laPiece->posP[3].y))
			&& (matrice[laPiece->posP[2].x + 1][laPiece->posP[2].y] == TET_VIDE
			|| (laPiece->posP[2].x + 1 == laPiece->posP[1].x && laPiece->posP[2].y == laPiece->posP[1].y)
			|| (laPiece->posP[2].x + 1 == laPiece->posP[0].x && laPiece->posP[2].y == laPiece->posP[0].y)
			|| (laPiece->posP[2].x + 1 == laPiece->posP[3].x && laPiece->posP[2].y == laPiece->posP[3].y))
			&& (matrice[laPiece->posP[3].x + 1][laPiece->posP[3].y] == TET_VIDE
			|| (laPiece->posP[3].x + 1 == laPiece->posP[1].x && laPiece->posP[3].y == laPiece->posP[1].y)
			|| (laPiece->posP[3].x + 1 == laPiece->posP[2].x && laPiece->posP[3].y == laPiece->posP[2].y)
			|| (laPiece->posP[3].x + 1 == laPiece->posP[0].x && laPiece->posP[3].y == laPiece->posP[0].y))) {
				matrice[laPiece->posP[0].x][laPiece->posP[0].y] = TET_VIDE;
				matrice[laPiece->posP[1].x][laPiece->posP[1].y] = TET_VIDE;
				matrice[laPiece->posP[2].x][laPiece->posP[2].y] = TET_VIDE;
				matrice[laPiece->posP[3].x][laPiece->posP[3].y] = TET_VIDE;

				matrice[laPiece->posP[0].x += 1][laPiece->posP[0].y] = laPiece->couleur;
				matrice[laPiece->posP[1].x += 1][laPiece->posP[1].y] = laPiece->couleur;
				matrice[laPiece->posP[2].x += 1][laPiece->posP[2].y] = laPiece->couleur;
				matrice[laPiece->posP[3].x += 1][laPiece->posP[3].y] = laPiece->couleur;
			}
		}
		break;
	default:
		break;
	}

	return retour;
}

/*******************************************/

void s_occuper_reserve(forme *laReserve) {
	int i, j, plusPetitX = laReserve->posP[0].x, plusPetitY = laReserve->posP[0].y;

	if(plusPetitX > laReserve->posP[1].x)
		plusPetitX = laReserve->posP[1].x;
	if(plusPetitX > laReserve->posP[2].x)
		plusPetitX = laReserve->posP[2].x;
	if(plusPetitX > laReserve->posP[3].x)
		plusPetitX = laReserve->posP[3].x;
	if(plusPetitY > laReserve->posP[1].y)
		plusPetitY = laReserve->posP[1].y;
	if(plusPetitY > laReserve->posP[2].y)
		plusPetitY = laReserve->posP[2].y;
	if(plusPetitY > laReserve->posP[3].y)
		plusPetitY = laReserve->posP[3].y;

	for(i = 0; i < 4; i++) {
		laReserve->posP[i].x -= (plusPetitX - 3);
		laReserve->posP[i].y -= plusPetitY;
	}

	for(j = 0; j < 4; j++) {
		move(TET_POS_RES_Y + j, TET_POS_RES_X - 2);

		for(i = 0; i < 12; i++)
			addch(' ');
	}

	if(laReserve->couleur) {
		afficher_bloc(TET_POS_RES_Y + laReserve->posP[0].y, TET_POS_RES_X +
		(laReserve->posP[0].x * 2) - (TET_LARGEUR - 4), laReserve->couleur);
		afficher_bloc(TET_POS_RES_Y + laReserve->posP[1].y, TET_POS_RES_X +
		(laReserve->posP[1].x * 2) - (TET_LARGEUR - 4), laReserve->couleur);
		afficher_bloc(TET_POS_RES_Y + laReserve->posP[2].y, TET_POS_RES_X +
		(laReserve->posP[2].x * 2) - (TET_LARGEUR - 4), laReserve->couleur);
		afficher_bloc(TET_POS_RES_Y + laReserve->posP[3].y, TET_POS_RES_X +
		(laReserve->posP[3].x * 2) - (TET_LARGEUR - 4), laReserve->couleur);
	}
}

/*******************************************/

void tet_enlever_ligne(int matrice[][TET_HAUTEUR], int y) {
	int i, j;

	for(i = y; i >= 1; i--) {
		for(j = 0; j < TET_LARGEUR; j++) {
			matrice[j][i] = matrice[j][i - 1];
			matrice[j][i - 1] = TET_VIDE;
		}
	}

	tetris_lignes++;
}

/*******************************************/

int recup_event(void) {
	int c = 0, retour = 0;
	c = getch();

	if(c == ERR)
		retour = TET_NO_EVENT;
	else if(c == touche_droite)
		retour = DROITE;
	else if(c == touche_gauche)
		retour = GAUCHE;
	else if(c == touche_bas)
		retour = BAS;
	else if(c == touche_haut)
		retour = HAUT;
	else if(c == ' ')
		retour = TET_TOURNER;
	else if(c == 'r')
		retour = TET_RESERVE;
	else if(c == '0')
		retour = TET_QUITTER;

	return retour;

}

/*******************************************/

int nouvelle_piece(int matrice[][TET_HAUTEUR], forme pieces[], forme *actuelle, forme *prochaine, forme *theReserve) {

	int i, j, perdu = 0, leRand, premiere = 0;
	forme *nouvelle, tampon;

	if(tetris_premier_appel++ == 0) {
		*actuelle = pieces[rand() % 7];
		leRand = rand() % 4;

		for(i = 0; i < leRand; i++)
			tet_tourner_forme(actuelle);

		actuelle->posP[0].x += TET_LARGEUR / 2 - 2;

		actuelle->posP[1].x += TET_LARGEUR / 2 - 2;

		actuelle->posP[2].x += TET_LARGEUR / 2 - 2;

		actuelle->posP[3].x += TET_LARGEUR / 2 - 2;

		/***********/

		*prochaine = pieces[rand() % 7];

		leRand = rand() % 4;

		for(i = 0; i < leRand; i++)
			tet_tourner_forme(prochaine);

		prochaine->posP[0].x += TET_LARGEUR / 2 - 2;

		prochaine->posP[1].x += TET_LARGEUR / 2 - 2;

		prochaine->posP[2].x += TET_LARGEUR / 2 - 2;

		prochaine->posP[3].x += TET_LARGEUR / 2 - 2;

		return perdu;
	}

	if(theReserve != NULL) {
		if(theReserve->couleur == 0) {
			nouvelle = prochaine;
			premiere = 1;
		}
		else
			nouvelle = theReserve;
	}
	else
		nouvelle = prochaine;

	if(theReserve != NULL) {
		matrice[actuelle->posP[0].x][actuelle->posP[0].y] = TET_VIDE;
		matrice[actuelle->posP[1].x][actuelle->posP[1].y] = TET_VIDE;
		matrice[actuelle->posP[2].x][actuelle->posP[2].y] = TET_VIDE;
		matrice[actuelle->posP[3].x][actuelle->posP[3].y] = TET_VIDE;
	}

	if(matrice[nouvelle->posP[0].x][nouvelle->posP[0].y]
	|| matrice[nouvelle->posP[1].x][nouvelle->posP[1].y]
	|| matrice[nouvelle->posP[2].x][nouvelle->posP[2].y]
	|| matrice[nouvelle->posP[3].x][nouvelle->posP[3].y])
		perdu = 1;
	else
		perdu = 0;

	matrice[nouvelle->posP[0].x][nouvelle->posP[0].y] = nouvelle->couleur;

	matrice[nouvelle->posP[1].x][nouvelle->posP[1].y] = nouvelle->couleur;

	matrice[nouvelle->posP[2].x][nouvelle->posP[2].y] = nouvelle->couleur;

	matrice[nouvelle->posP[3].x][nouvelle->posP[3].y] = nouvelle->couleur;

	tampon = *nouvelle;

	if(theReserve != NULL)
		*theReserve = *actuelle;

	*actuelle = tampon;

	if(theReserve == NULL || premiere) {
		*nouvelle = pieces[rand() % 7];

		leRand = rand() % 4;

		for(i = 0; i < leRand; i++)
			tet_tourner_forme(nouvelle);

		nouvelle->posP[0].x += TET_LARGEUR / 2 - 2;

		nouvelle->posP[1].x += TET_LARGEUR / 2 - 2;

		nouvelle->posP[2].x += TET_LARGEUR / 2 - 2;

		nouvelle->posP[3].x += TET_LARGEUR / 2 - 2;

		for(j = 0; j < 4; j++) {
			move(TET_POS_PROCH_Y + j, TET_POS_PROCH_X - 2);

			for(i = 0; i < 12; i++)
				addch(' ');
		}

		afficher_bloc(TET_POS_PROCH_Y + nouvelle->posP[0].y, TET_POS_PROCH_X +
		(nouvelle->posP[0].x * 2) - TET_LARGEUR / 2 - 2, nouvelle->couleur);
		afficher_bloc(TET_POS_PROCH_Y + nouvelle->posP[1].y, TET_POS_PROCH_X +
		(nouvelle->posP[1].x * 2) - TET_LARGEUR / 2 - 2, nouvelle->couleur);
		afficher_bloc(TET_POS_PROCH_Y + nouvelle->posP[2].y, TET_POS_PROCH_X +
		(nouvelle->posP[2].x * 2) - TET_LARGEUR / 2 - 2, nouvelle->couleur);
		afficher_bloc(TET_POS_PROCH_Y + nouvelle->posP[3].y, TET_POS_PROCH_X +
		(nouvelle->posP[3].x * 2) - TET_LARGEUR / 2 - 2, nouvelle->couleur);
	}

	return perdu;

}

/*******************************************/

void rajouter_ligne(int matrice[][TET_HAUTEUR]) {
	int i, j, leRand;

	for(i = 0; i < TET_HAUTEUR - 1; i++) {
		for(j = 0; j < TET_LARGEUR; j++)
			matrice[j][i] = matrice[j][i + 1];
	}

	for(j = 0; j < TET_LARGEUR; j++)
		matrice[j][TET_HAUTEUR - 1] = TET_VIDE;

	for(j = 0; j < (TET_LARGEUR * 4) / 5; j++) {
		while(matrice[leRand = rand() % TET_LARGEUR][TET_HAUTEUR - 1])
			;

		matrice[leRand][TET_HAUTEUR - 1] = random(1, 7);

	}
}

/*******************************************/

int descendre_piece(int matrice[][TET_HAUTEUR], forme *piece) {
	if(piece->posP[0].y < TET_HAUTEUR - 1 && piece->posP[1].y < TET_HAUTEUR - 1 &&
	piece->posP[2].y < TET_HAUTEUR - 1 && piece->posP[3].y < TET_HAUTEUR - 1
	&& (matrice[piece->posP[0].x][piece->posP[0].y + 1] == TET_VIDE
	|| (piece->posP[0].x == piece->posP[1].x && piece->posP[0].y + 1 == piece->posP[1].y)
	|| (piece->posP[0].x == piece->posP[2].x && piece->posP[0].y + 1 == piece->posP[2].y)
	|| (piece->posP[0].x == piece->posP[3].x && piece->posP[0].y + 1 == piece->posP[3].y))
	&& (matrice[piece->posP[1].x][piece->posP[1].y + 1] == TET_VIDE
	|| (piece->posP[1].x == piece->posP[0].x && piece->posP[1].y + 1 == piece->posP[0].y)
	|| (piece->posP[1].x == piece->posP[2].x && piece->posP[1].y + 1 == piece->posP[2].y)
	|| (piece->posP[1].x == piece->posP[3].x && piece->posP[1].y + 1 == piece->posP[3].y))
	&& (matrice[piece->posP[2].x][piece->posP[2].y + 1] == TET_VIDE
	|| (piece->posP[2].x == piece->posP[1].x && piece->posP[2].y + 1 == piece->posP[1].y)
	|| (piece->posP[2].x == piece->posP[0].x && piece->posP[2].y + 1 == piece->posP[0].y)
	|| (piece->posP[2].x == piece->posP[3].x && piece->posP[2].y + 1 == piece->posP[3].y))
	&& (matrice[piece->posP[3].x][piece->posP[3].y + 1] == TET_VIDE
	|| (piece->posP[3].x == piece->posP[1].x && piece->posP[3].y + 1 == piece->posP[1].y)
	|| (piece->posP[3].x == piece->posP[2].x && piece->posP[3].y + 1 == piece->posP[2].y)
	|| (piece->posP[3].x == piece->posP[0].x && piece->posP[3].y + 1 == piece->posP[0].y))) {
		matrice[piece->posP[0].x][piece->posP[0].y] = TET_VIDE;
		matrice[piece->posP[1].x][piece->posP[1].y] = TET_VIDE;
		matrice[piece->posP[2].x][piece->posP[2].y] = TET_VIDE;
		matrice[piece->posP[3].x][piece->posP[3].y] = TET_VIDE;
		matrice[piece->posP[0].x][++(piece->posP[0].y)] = piece->couleur;
		matrice[piece->posP[1].x][++(piece->posP[1].y)] = piece->couleur;
		matrice[piece->posP[2].x][++(piece->posP[2].y)] = piece->couleur;
		matrice[piece->posP[3].x][++(piece->posP[3].y)] = piece->couleur;
		return 0;
	}
	else {
		tetris_points++;
		return 1;
	}

}
